package controllers;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import javax.swing.JOptionPane;

import Client.Model.*;
import Client.Model.*;
import models.msgs.*;
import models.msgs.Number;
import play.Logger;
import play.mvc.*;
import play.libs.*;
import play.libs.F.*;
import scala.concurrent.Await;
import scala.concurrent.duration.Duration;
import exceptions.*;
import akka.actor.*;
import static akka.pattern.Patterns.ask;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.fasterxml.jackson.databind.node.ArrayNode;

import static java.util.concurrent.TimeUnit.*;

public class Human extends UntypedActor
{
    public final String               name;
    public final ActorRef             table;
    
    
    protected WebSocket.In<JsonNode>  in;
    protected WebSocket.Out<JsonNode> out;
    
    private Connection_Model transfer;
    private Rules_Model rules;
    

    public Human(String _name, WebSocket.In<JsonNode> _in,
            WebSocket.Out<JsonNode> _out, ActorRef _table)
    {
        name = _name;        
        table = _table;
        in = _in;
        out = _out;
        
        rules = new Rules_Model();
        transfer = new Connection_Model(rules, this);
        
        
        in.onMessage(new Callback<JsonNode>()
        {
            @Override
            public void invoke(JsonNode event)
            {
                try
                {
                	String input = event.get("nr").asText();
                	String[] cmd = input.split(" ");
                	if(cmd.length == 0)
                		return;
                	else if("cards".equals(cmd[0]))
                		showCards();
                	else if("change".equals(cmd[0]))
                	{
                		// wymieniam
                		int[] c = new int[5];
                		c[0] = cmd.length - 1;
                		for(int i=1; i<cmd.length; i++)
                			c[i] = Integer.parseInt(cmd[i]);
                		
                		// wymiana kart
                		String msgout = "3"+c[0]; // do zrobienia.
                		for (int i=1; i<=c[0]; i++)
                			msgout += c[i];
                		table.tell(new ClientMessage(msgout, rules.MyID()), getSelf());
                		rules.TurnId(-1);
                		rules.SetChangability(false);
                		rules.NextRound();
                	}
                	else if("check".equals(cmd[0]))
                	{
                		// wymieniam
                		rules.Auction(rules.MyID(), 0, 0);
                		String output = new String();
                		output = "20";
                		rules.TurnId(-1);
                		table.tell(new ClientMessage(output, rules.MyID()), getSelf());
                	}
                	else if("fold".equals(cmd[0]))
                	{
                		// wymieniam
                		rules.Auction(rules.MyID(), 4, 0);
                		String output = new String();
                		output = "24";
                		rules.TurnId(-1);
                		table.tell(new ClientMessage(output, rules.MyID()), getSelf());
                	}
                	else if("bet".equals(cmd[0]))
                	{
                		// wymieniam
                		String output = new String();
                		if(cmd.length == 1)
                			return;
                		String my_bet = cmd[1];
                		int x = Integer.parseInt(my_bet);
                		int[] a = new int[3];
                		a = rules.getAcc();
                		if (x > 0 && a[0] > ((a[2] - a[1]) + x))
                		{
                				rules.Auction(rules.MyID(), 1, x);//bet
                				output = "21;"+x;
                				rules.TurnId(-1);
                				table.tell(new ClientMessage(output, rules.MyID()), getSelf());
                		}
                	}
                	else if("raise".equals(cmd[0]))
                	{
                		String output = new String();
                		if(cmd.length == 1)
                			return;
                		String my_bet = cmd[1];
                		int x = Integer.parseInt(my_bet);
                		int[] a = new int[3];
                		a = rules.getAcc();
                		if (x > 0 && a[0] > ((a[2] - a[1]) + x))
                		{
                			rules.Auction(rules.MyID(), 2, x);//raise
                			output = "22;"+x;
                			rules.TurnId(-1);
                			table.tell(new ClientMessage(output, rules.MyID()), getSelf());
                		}
                	}
                	else if("call".equals(cmd[0]))
                	{
                		// wymieniam
                		String output = new String();
                		rules.Auction(rules.MyID(), 3, 0);//call
                		output = "23";
                		rules.TurnId(-1);
                		JOptionPane.showMessageDialog(null, output + " "+rules.MyID());
                		table.tell(new ClientMessage(output, rules.MyID()), getSelf());
                	}
                	else if("allin".equals(cmd[0]))
                	{
                		// wymieniam
                		rules.Auction(rules.MyID(), 5, 0);//all in
            			String output = "25";
            			rules.TurnId(-1);
            			table.tell(new ClientMessage(output, rules.MyID()), getSelf());
                	}               	
                }
                catch (Exception e)
                {
                    Logger.error("invokeError");
                }
                
            }
        });

        in.onClose(new Callback0()
        {
            @Override
            public void invoke()
            {
                table.tell(new ClientMessage("9",rules.MyID()), getSelf() );
            }
        });
    }

    public void setMyID(int id)
	{
		//game_view.setMyID(id);
	}
	
	public void setMyNick(String nick)
	{
		//game_view.setMyNick(nick);
		rules.SetMyNick(nick);
	}

	public void AddPlayer(String nick, int id)
	{
		//game_view.AddPlayer(nick, id);
	}
	
    @Override
    public void onReceive(Object _msg) throws Exception
    {
    	if(_msg instanceof ClientMessage)
    	{
    		transfer.ReceiveMsg(((ClientMessage)_msg).getMsg());
    		// do nothing.
    		String ciul = ((ClientMessage)_msg).getMsg();
    		
    	}
    	else if(_msg instanceof String)
    	{
    		ObjectNode event = Json.newObject();
            event.put("message", (String)_msg); 
            out.write(event);
    	}
    	else {
    		unhandled(_msg);
    	}
    }
    
    private void showCards()
    {
    	String ciul2 = "";
		int[] moje_wafle = rules.getCards();
		for(int j=0; j<moje_wafle[0]; j++)
		{
			ciul2 += ""+rules.player[moje_wafle[1 + (j * 5) - 1]].getNick()+"'s cards: ";
			
			for(int i=1+(j*5)+1; i<1+(j*5)+5; i++)
			{
				if((moje_wafle[i]%13) <= 8)
					ciul2 += (moje_wafle[i]%13) + 2;
				else
				{
					switch((moje_wafle[i]%13) - 9)
					{
					case 0: ciul2 += " walet "; break;
					case 1: ciul2 += " dama "; break;
					case 2: ciul2 += " król "; break;
					case 3: ciul2 += " as "; break;
					}
				}
				switch(moje_wafle[i]/13)
				{
				case 0: ciul2 += " kier "; break;
				case 1: ciul2 += " karo "; break;
				case 2: ciul2 += " trefl "; break;
				case 3: ciul2 += " pik "; break;
				}
				ciul2 += "\n";
			}
		}
		
		ObjectNode event = Json.newObject();
        event.put("message", (String)ciul2); 
        out.write(event);
    }
    
}
            


